using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Web.UI;
using OpenWaves.Web;
using OpenWaves.Web.Controls;

namespace OpenWaves.Navigation.Controls
{
    [ParseChildren(true)]
    [PersistChildren(false)]
    public abstract class NavigationView<T> : TreeView<T> where T : ITreeNode<T>
    {
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate NodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate FirstLevelNodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate SecondLevelNodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate ThirdLevelNodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate FourthLevelNodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate FifthLevelNodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate ExpandedNodeTemplate { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(INavigationNodeContainer))]
        public virtual ITemplate CurrentNodeTemplate { get; set; }

        private INavigationViewModel<T> model;
        public INavigationViewModel<T> Model
        {
            get { return this.model; }
            set
            {
                this.model = value;
                base.DataSource = value.RootNodes;
            }
        }

        protected override bool IsNodeVisible(T node)
        {
            return this.Model.IsNodeVisible(node);
        }

        protected override ITemplate ResolveNodeTemplate(T node, int level)
        {
            if (level == 1 && this.FirstLevelNodeTemplate != null)
                return this.FirstLevelNodeTemplate;
            else if (level == 2 && this.SecondLevelNodeTemplate != null)
                return this.SecondLevelNodeTemplate;
            else if (level == 3 && this.ThirdLevelNodeTemplate != null)
                return this.ThirdLevelNodeTemplate;
            else if (level == 4 && this.FourthLevelNodeTemplate != null)
                return this.FourthLevelNodeTemplate;
            else if (level == 5 && this.FifthLevelNodeTemplate != null)
                return this.FifthLevelNodeTemplate;

            switch(this.Model.GetNodeState(node))
            {
                case NavigationNodeState.Current:
                    return this.CurrentNodeTemplate ?? this.ExpandedNodeTemplate ?? this.NodeTemplate;

                case NavigationNodeState.Expanded:
                    return this.ExpandedNodeTemplate ?? this.NodeTemplate;

                default:
                    return this.NodeTemplate;
            }
        }

        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "FxCop is stupid and does not work well with CodeContracts.")]
        protected override TreeNodeContainer<T> CreateNodeContainer(T node, int nodeIndex, int nodeLevel)
        {
            return new NavigationNodeContainer<T>(node, nodeIndex, nodeLevel, this.Model.GetNodeState(node), node.Children.Any(this.IsNodeVisible));
        }
    }
}